package com.ruoyi.asms.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.asms.domain.AsmsFaultAsset;
import com.ruoyi.asms.domain.AsmsFaultConfirmStage;
import com.ruoyi.asms.domain.AsmsFaultDispatchStage;
import com.ruoyi.asms.domain.FaultInfoView;
import com.ruoyi.asms.domain.vo.MyWorkOrderListVo;
import com.ruoyi.asms.domain.vo.TotalResovleFaultAnalysisVo;
import com.ruoyi.asms.domain.vo.TotalWorkOrderListVo;
import com.ruoyi.asms.service.*;
import com.ruoyi.common.core.domain.AsmsAssetFullInfo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.statistics.vo.NewPieChartVo;
import com.ruoyi.common.core.utils.BusinessUtils;
import com.ruoyi.common.core.utils.SecurityUtils;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.security.service.TokensService;
import com.ruoyi.system.controller.SysUserController;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author WJH
 * @description 微信小程序数据统计
 * @date 2022/8/11 15:59
 */
@RestController
@RequestMapping("/asms/wxDataStat")
public class AsmsWxDataStatController {

    @Autowired
    private AsmsReusingService asmsReusingService;
    @Autowired
    private IAsmsFaultConfirmStageService faultConfirmStageService;
    @Autowired
    private IAsmsFaultAssetService asmsFaultAssetService;
    @Autowired
    private IAsmsAssetFullInfoService assetFullInfoService;
    @Autowired
    private TokensService tokenService;
    @Autowired
    private IFaultInfoViewService faultInfoViewService;

    @Autowired
    private IAsmsFaultDispatchStageService faultDispatchStageService;

//    @Autowired
//    private RemoteUserService remoteUserService;
    @Autowired
    private SysUserController userController;

    /**
     * 将技术人员数据统计公共部分抽离出来
     * @param period
     * @return
     */
    private List<AsmsFaultAsset> getFaultAssets(Integer period) {
        QueryWrapper<AsmsFaultAsset> wrapper = new QueryWrapper<>();
        wrapper.eq(AsmsFaultAsset.FAULT_RESOLVE_USER_ID, SecurityUtils.getUserId())
                .select(AsmsFaultAsset.FAULT_ASSET_ID, AsmsFaultAsset.STAGE, AsmsFaultAsset.ASSET_ID, AsmsFaultAsset.CREATE_TIME)
                .lt(AsmsFaultAsset.CREATE_TIME, System.currentTimeMillis());
        switch (period) {
            case 0:
                wrapper.gt(AsmsFaultAsset.CREATE_TIME, asmsReusingService.getTodayStartTime());
                break;
            case 1:
                wrapper.gt(AsmsFaultAsset.CREATE_TIME, asmsReusingService.getThisWeekStartTime());
                break;
            case 2:
                wrapper.gt(AsmsFaultAsset.CREATE_TIME, asmsReusingService.getThisMonthStartTime());
                break;
            case 3:
                wrapper.gt(AsmsFaultAsset.CREATE_TIME, asmsReusingService.getThisYearStartTime());
                break;
        }
        return asmsFaultAssetService.list(wrapper);
    }

    @ApiOperation(value = "统计分析之故障处理总体分析", response = TotalResovleFaultAnalysisVo.class)
    @GetMapping("/myResovleFaultAnalysis")
    public R<TotalResovleFaultAnalysisVo> myResovleFaultAnalysis(@ApiParam("0今日 1本周 2本月 3今年") @RequestParam("period") Integer period) {
        TotalResovleFaultAnalysisVo result = new TotalResovleFaultAnalysisVo();
        result.setNum(0).setResovleRate("未知").setGoodRate("未知");
        //按时间周期查询我负责维修的故障
        List<AsmsFaultAsset> list = getFaultAssets(period);
        if (list.size() == 0) {
            return R.ok(result);
        }

        //计算未解决故障的数量
        Long unResovleNum = list.stream().filter(o -> o.getStage().equals(3)).count();
        result.setNum(unResovleNum.intValue());

        //计算解决率
        Long hasResovleNum = list.stream().filter(o -> o.getStage().equals(4)).count();
        String resovleRateStr = asmsReusingService.keepTwoDecimalDiv(hasResovleNum.intValue(), list.size());
        String resovleRate = String.format("%.0f", Float.parseFloat(resovleRateStr) * 100) + "%";
        result.setResovleRate(resovleRate);

        //计算好评率
        Set<Long> faultAssetIds = list.stream().map(AsmsFaultAsset::getFaultAssetId).collect(Collectors.toSet());
        List<AsmsFaultConfirmStage> confirmStages = faultConfirmStageService.list(new QueryWrapper<AsmsFaultConfirmStage>()
                .in(AsmsFaultConfirmStage.FAULT_ASSET_ID, faultAssetIds).isNotNull(AsmsFaultConfirmStage.END_TIME)
        );
        if (confirmStages.size() == 0) {
            return R.ok(result);
        }
        Long goodNum = confirmStages.stream().filter(o -> o.getAttitudeScore().equals(5) && o.getEfficiencyScore().equals(5)
                && o.getQualityScore().equals(5)).count();
        String goodRateStr = asmsReusingService.keepTwoDecimalDiv(goodNum.intValue(), confirmStages.size());
        String goodRate = String.format("%.0f", Float.parseFloat(goodRateStr) * 100) + "%";
        result.setGoodRate(goodRate);

        return R.ok(result);
    }

    @ApiOperation(value = "统计分析之我的工单处理列表统计", response = MyWorkOrderListVo.class)
    @GetMapping("/myWorkOrderList")
    public R<List<MyWorkOrderListVo>> myWorkOrderList(@ApiParam("0今日 1本周 2本月 3今年") @RequestParam("period") Integer period) {
        List<MyWorkOrderListVo> result = new ArrayList<>();
        List<AsmsFaultAsset> faultAssets = getFaultAssets(period);
        if (faultAssets.size() == 0) {
            return R.ok(result);
        }
        Map<Long, Integer> faultStageMap = faultAssets.stream().collect(Collectors.toMap(AsmsFaultAsset::getFaultAssetId, AsmsFaultAsset::getStage));
        Set<Long> assetIds = faultAssets.stream().map(AsmsFaultAsset::getAssetId).collect(Collectors.toSet());

        List<AsmsAssetFullInfo> assets = assetFullInfoService.list(new QueryWrapper<AsmsAssetFullInfo>()
                .select(AsmsAssetFullInfo.ASSET_TYPE_NAME, AsmsAssetFullInfo.ASSET_ID, AsmsAssetFullInfo.OWN_DEPT_NAME)
                .in(AsmsAssetFullInfo.ASSET_ID, assetIds)
        );
        Map<Long, AsmsAssetFullInfo> assetMap = assets.stream().collect(Collectors.toMap(AsmsAssetFullInfo::getAssetId, a -> a));

        faultAssets.forEach(fa -> {
            MyWorkOrderListVo vo = new MyWorkOrderListVo();
            AsmsAssetFullInfo assetInfo = assetMap.get(fa.getAssetId());
            if (Objects.nonNull(assetInfo)) {
                vo.setDeptName(assetInfo.getOwnDeptName());
                vo.setFaultAssetName(assetInfo.getAssetTypeName());
            }
            vo.setReportTime(fa.getCreateTime());
            Integer stage = faultStageMap.get(fa.getFaultAssetId());
            vo.setIsResovle(stage.equals(4) ? 0 : 1);
            result.add(vo);
        });
        result.sort(Comparator.comparing(MyWorkOrderListVo::getReportTime).reversed());
        return R.ok(result);
    }

    @ApiOperation("统计分析之查看已处理与未处理的占比")
    @GetMapping("/resovleAndUnResovle")
    public AjaxResult resovleAndUnResovle(@ApiParam("0今日 1本周 2本月 3今年") @RequestParam("period") Integer period) {
        List<NewPieChartVo> result = new ArrayList<>();
        List<AsmsFaultAsset> faultAssets = getFaultAssets(period);
        if (faultAssets.size() == 0) {
            return AjaxResult.success(result);
        }
        //查询未处理的故障数量
        Long unResovleNum = faultAssets.stream().filter(fa -> fa.getStage().equals(3)).count();

        //查询已处理的故障数量
        Long hasResovleNum = faultAssets.stream().filter(fa -> fa.getStage().equals(4)).count();

        NewPieChartVo unResovlePie = new NewPieChartVo();
        unResovlePie.setName("未处理").setValue(unResovleNum.intValue());
        result.add(unResovlePie);

        NewPieChartVo resovlePie = new NewPieChartVo();
        resovlePie.setName("已处理").setValue(hasResovleNum.intValue());
        result.add(resovlePie);

        return AjaxResult.success(result);
    }

    /**
     * 维护方管理员获取故障本部门所维护的资产
     * @return
     */
    private List<AsmsFaultAsset> getFaultAssetsByAdmin() {
        List<AsmsFaultAsset> result = new ArrayList<>();
        Set<Long> deptIds = tokenService.getUserMaintenanceDeptIds();
        if (Objects.nonNull(deptIds) && deptIds.size() != 0) {
            result = asmsFaultAssetService.list(new QueryWrapper<AsmsFaultAsset>()
                    .select(AsmsFaultAsset.FAULT_ASSET_ID, AsmsFaultAsset.STAGE, AsmsFaultAsset.FAULT_RESOLVE_USER_ID,
                            AsmsFaultAsset.ASSET_ID)
                    .in(AsmsFaultAsset.MAINTENANCE_DEPT_ID, deptIds)
            );
        }
        return result;
    }

    @ApiOperation(value = "运营分析之总体分析", response = TotalResovleFaultAnalysisVo.class)
    @GetMapping("/totalAnalysis")
    public R<TotalResovleFaultAnalysisVo> totalAnalysis() {
        TotalResovleFaultAnalysisVo result = new TotalResovleFaultAnalysisVo();
        result.setNum(0).setGoodRate("未知").setResovleRate("未知");
        List<AsmsFaultAsset> faultAssets = getFaultAssetsByAdmin();
        if (faultAssets.size() == 0) {
            return R.ok(result);
        }
        Set<Long> faultAssetIds = faultAssets.stream().map(AsmsFaultAsset::getFaultAssetId).collect(Collectors.toSet());

        //计算服务用户数
        List<FaultInfoView> views = faultInfoViewService.list(new QueryWrapper<FaultInfoView>()
                .select(FaultInfoView.FAULT_ASSET_ID, FaultInfoView.FAULT_FIND_USER_ID)
                .in(FaultInfoView.FAULT_ASSET_ID, faultAssetIds)
        );
        Set<Long> finderIds = views.stream().map(FaultInfoView::getFaultFindUserId).collect(Collectors.toSet());
        result.setNum(finderIds.size());

        //计算解决率
        Long hasResovleNum = faultAssets.stream().filter(o -> o.getStage().equals(4)).count();
        String resovleRateStr = asmsReusingService.keepTwoDecimalDiv(hasResovleNum.intValue(), faultAssets.size());
        String resovleRate = String.format("%.0f", Float.parseFloat(resovleRateStr) * 100) + "%";
        result.setResovleRate(resovleRate);

        //计算好评率
        List<AsmsFaultConfirmStage> stageList = faultConfirmStageService.list(new QueryWrapper<AsmsFaultConfirmStage>()
                .select(AsmsFaultConfirmStage.ATTITUDE_SCORE, AsmsFaultConfirmStage.EFFICIENCY_SCORE, AsmsFaultConfirmStage.QUALITY_SCORE)
                .isNotNull(AsmsFaultConfirmStage.END_TIME).in(AsmsFaultConfirmStage.FAULT_ASSET_ID, faultAssetIds)
        );
        if (stageList.size() == 0) {
            return R.ok(result);
        }
        Long goodNum = stageList.stream().filter(c -> c.getQualityScore().equals(5) && c.getEfficiencyScore().equals(5)
                && c.getAttitudeScore().equals(5)).count();
        String goodRateStr = asmsReusingService.keepTwoDecimalDiv(goodNum.intValue(), stageList.size());
        String goodRate = String.format("%.0f", Float.parseFloat(goodRateStr) * 100) + "%";
        result.setGoodRate(goodRate);

        return R.ok(result);
    }

    @ApiOperation(value = "运营分析之查看工单处理情况")
    @GetMapping("/totalWorkOrderList")
    public R<List<TotalWorkOrderListVo>> totalWorkOrderList() {
        List<TotalWorkOrderListVo> result = new ArrayList<>();
        List<AsmsFaultAsset> faultAssets = getFaultAssetsByAdmin();
        if (faultAssets.size() == 0) {
            return R.ok(result);
        }
        Set<Long> faultAssetIds = faultAssets.stream().map(AsmsFaultAsset::getFaultAssetId).collect(Collectors.toSet());

        //查询派单时间
        List<AsmsFaultDispatchStage> stageList = faultDispatchStageService.list(new QueryWrapper<AsmsFaultDispatchStage>()
                .select(AsmsFaultDispatchStage.FAULT_ASSET_ID, AsmsFaultDispatchStage.END_TIME)
                .in(AsmsFaultDispatchStage.FAULT_ASSET_ID, faultAssetIds)
        );
        Map<Long, Long> dispatchMap = stageList.stream().filter(o -> Objects.nonNull(o.getEndTime()))
                .collect(Collectors.toMap(AsmsFaultDispatchStage::getFaultAssetId, AsmsFaultDispatchStage::getEndTime));

        //查询维修人员
        Set<Long> repairIds = faultAssets.stream().filter(o -> Objects.nonNull(o.getFaultResolveUserId())).map(AsmsFaultAsset::getFaultResolveUserId).collect(Collectors.toSet());
        R<Map<Long, SysUser>> usersR = userController.getUserListByIds(repairIds.toArray(new Long[0]));
        BusinessUtils.checkRemoteService(usersR);
        Map<Long, SysUser> userMap = usersR.getData();

        //查询资产信息
        Set<Long> assetIds = faultAssets.stream().map(AsmsFaultAsset::getAssetId).collect(Collectors.toSet());
        List<AsmsAssetFullInfo> assets = assetFullInfoService.list(new QueryWrapper<AsmsAssetFullInfo>()
                .select(AsmsAssetFullInfo.ASSET_ID, AsmsAssetFullInfo.OWN_DEPT_NAME, AsmsAssetFullInfo.ASSET_TYPE_NAME)
                .in(AsmsAssetFullInfo.ASSET_ID, assetIds)
        );
        Map<Long, AsmsAssetFullInfo> assetMap = assets.stream().collect(Collectors.toMap(AsmsAssetFullInfo::getAssetId, o -> o));

        //构造列表数据
        faultAssets.sort(Comparator.comparing(AsmsFaultAsset::getFaultAssetId).reversed());
        for (AsmsFaultAsset faultAsset : faultAssets) {
            TotalWorkOrderListVo vo = new TotalWorkOrderListVo();
            AsmsAssetFullInfo asset = assetMap.get(faultAsset.getAssetId());
            if (Objects.nonNull(asset)) {
                vo.setDeptName(asset.getOwnDeptName());
                vo.setFaultAssetName(asset.getAssetTypeName());
            }
            vo.setDisptachWorkTime(dispatchMap.get(faultAsset.getFaultAssetId()));
            vo.setIsResovle(faultAsset.getStage().equals(4) ? 0 : 1);
            SysUser user = userMap.get(faultAsset.getFaultResolveUserId());
            if (Objects.nonNull(user)) {
                vo.setRepairName(user.getNickName());
            }
            result.add(vo);
        }
        return R.ok(result);
    }

    @ApiOperation("运营分析之维修人员处理情况")
    @GetMapping("/faultResovleWithRepair")
    public AjaxResult faultResovleWithRepair() {
        List<NewPieChartVo> result = new ArrayList<>();
        List<AsmsFaultAsset> faultAssetList = getFaultAssetsByAdmin();
        if (faultAssetList.size() == 0) {
            return AjaxResult.success(result);
        }
        R<List<SysUser>> listR =userController.getResovlersByDeptId(SecurityUtils.getDeptId());
        BusinessUtils.checkRemoteService(listR);
        for (SysUser user : listR.getData()) {
            NewPieChartVo vo = new NewPieChartVo();
            vo.setName(user.getNickName());
            Long count = faultAssetList.stream().filter(f -> Objects.nonNull(f.getFaultResolveUserId()) &&
                    f.getFaultResolveUserId().equals(user.getUserId()) && f.getStage().equals(4)).count();
            vo.setValue(count.intValue());
            result.add(vo);
        }
        result.sort(Comparator.comparing(NewPieChartVo::getValue).reversed());
        return AjaxResult.success(result);
    }
}
